package nancal.mp.db.mq


import nbcp.base.extend.AllGetPropertyMethods
import nbcp.base.extend.AsString
import nbcp.base.extend.GetEnumList
import nbcp.base.extend.Slice
import nbcp.base.utils.SpringUtil
import nbcp.base.utils.StringUtil
import nbcp.myoql.db.rabbit.IMqProxy
import org.slf4j.LoggerFactory
import org.springframework.amqp.core.BindingBuilder
import org.springframework.amqp.core.DirectExchange
import org.springframework.amqp.core.Queue
import org.springframework.amqp.rabbit.connection.ConnectionFactory
import org.springframework.amqp.rabbit.core.RabbitAdmin
import org.springframework.amqp.rabbit.core.RabbitTemplate
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter
import org.springframework.amqp.support.converter.MessageConverter
import org.springframework.beans.factory.InitializingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.lang.reflect.Modifier

@Configuration
@ConditionalOnProperty("spring.rabbitmq.virtual-host")
open class MqConfig : InitializingBean {
    companion object {
        private val logger = LoggerFactory.getLogger(this::class.java.declaringClass)
    }

    @Bean
    fun messageConverter(): MessageConverter {
        return Jackson2JsonMessageConverter();
    }


    override fun afterPropertiesSet() {
        if (SpringUtil.containsBean<RabbitTemplate>() == false) {
            return;
        }

        var groups = mqr.javaClass.declaredFields
            .filter { Modifier.isStatic(mqr.javaClass.declaredFields[1].modifiers) && it.type.simpleName.endsWith("Group") }
            .map {
                it.isAccessible = true;
                it.get(null)
            }


        groups.forEach { group ->
            group::class.java.methods
                .filter { IMqProxy::class.java.isAssignableFrom(it.returnType) }
                .forEach { method ->
                    if (method.parameterCount == 0) {
                        var mqProxy = method.invoke(group) as IMqProxy;

                        mqProxy.declareMqBinding()
                        return@forEach;
                    }
                    if (method.parameterCount == 1) {
                        var p0 = method.parameters.get(0);
                        if (p0.type.isEnum) {
                            p0.type.GetEnumList().forEach { enumItem ->

                                var mqProxy = method.invoke(group, enumItem) as IMqProxy;
                                mqProxy.declareMqBinding()
                            }
                        }
                    }
                }
        }


//        var connectionFactory = SpringUtil.getBean<ConnectionFactory>();
//        var template = SpringUtil.getBean<RabbitTemplate>();
//
//        if (connectionFactory.isPublisherConfirms) {
//            //如果消息没有到exchange,则confirm回调,ack=false
//            //如果消息到达exchange,则confirm回调,ack=true
//            template.setConfirmCallback { correlationData, ack, _ ->
//                if (correlationData == null) return@setConfirmCallback;
//                if (correlationData.id == null) return@setConfirmCallback;
//
//                if (!ack) {
//                    logger.error("${correlationData.id}, 消息:${correlationData.returned.message.body}, 确认阶段失败, 发送失败")
//                }
//            }
//        }
//
//        if (connectionFactory.isPublisherReturns) {
//            template.setMandatory(true);
//            //exchange到queue成功,则不回调return
//            //exchange到queue失败,则回调return(需设置mandatory=true,否则不回回调,消息就丢了)
//            template.setReturnsCallback { message ->
//                var logId = message.message.messageProperties.headers["log-id"].AsString()
//
//                logger.error("${message.exchange}-${message.routingKey}:${logId}, 消息:${message.message.body}, 返回 ${message.replyCode}-${message.replyText}")
//            }
//        }

        return;
    }


//    private fun declareBind(name: String) {
//        var connectionFactory = SpringUtil.getBean<ConnectionFactory>();
//        var admin = RabbitAdmin(connectionFactory);
//
//        var exchange = DirectExchange(name);
//        admin.declareExchange(exchange)
//
//        var queue = Queue(name);
//        admin.declareQueue(queue);
//
//        admin.declareBinding(
//                BindingBuilder
//                        .bind(queue)
//                        .to(exchange)
//                        .withQueueName()
//        )
//    }
}
